package com.ming.common.liteflow.context;

import com.ming.common.beetl.util.BeetlSqlUtil;
import com.ming.common.liteflow.core.chain.IvyChain;
import com.ming.common.liteflow.core.config.IvyConfig;
import com.ming.common.liteflow.core.el.IvyEl;
import com.ming.common.liteflow.core.flowexecutor.FlowExecutorUtil;
import com.ming.common.liteflow.core.flowexecutor.IvyExecutor;
import com.ming.common.xxljob.context.XxlJobContext;
import com.ming.common.xxljob.context.XxlJobHelper;
import com.yomahub.liteflow.builder.el.LiteFlowChainELBuilder;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import org.beetl.sql.core.SQLReady;
import org.beetl.sql.core.query.LambdaQuery;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

public class IvyHelper {

    private static final String sql = "select chain_id from xxl_job_info where id = ?";

    public static LiteflowResponse exec(){
        XxlJobContext xxlJobContext = XxlJobContext.getXxlJobContext();
        String chainId = BeetlSqlUtil.NEW().getDefaultSQLManager().execute(new SQLReady(sql, xxlJobContext.getJobId()), String.class).stream().findFirst().orElse(null);
        return exec(chainId);
    }

    public static LiteflowResponse exec(Integer ivyChainId){
        return exec((long) ivyChainId);
    }

    public static LiteflowResponse exec(Long ivyChainId){
        LambdaQuery<IvyChain> chainLambdaQuery = BeetlSqlUtil.NEW().defaultSQLManager().tableName(IvyChain.class).lambdaQuery();
        IvyChain ivyChain = chainLambdaQuery.andEq(IvyChain::getId, ivyChainId).single();
        return exec(ivyChain);
    }

    public static LiteflowResponse exec(String ivyChainId){
        LambdaQuery<IvyChain> chainLambdaQuery = BeetlSqlUtil.NEW().defaultSQLManager().tableName(IvyChain.class).lambdaQuery();
        IvyChain ivyChain = chainLambdaQuery.andEq(IvyChain::getChainId, ivyChainId).single();
        return exec(ivyChain);
    }

    public static LiteflowResponse exec(IvyChain ivyChain){
        try {
            LambdaQuery<IvyEl> elLambdaQuery = BeetlSqlUtil.NEW().defaultSQLManager().tableName(IvyEl.class).lambdaQuery();
            IvyEl ivyEl = elLambdaQuery.andEq(IvyEl::getId, ivyChain.getIvyElId()).single();

            if(ivyEl.getExecutorId() == null){
                throw new RuntimeException("ivy_el表executor_id不能为空！");
            }

            LambdaQuery<IvyExecutor> executorLambdaQuery = BeetlSqlUtil.NEW().defaultSQLManager().tableName(IvyExecutor.class).lambdaQuery();
            IvyExecutor ivyExecutor = executorLambdaQuery.andEq(IvyExecutor::getId, ivyEl.getExecutorId()).single();

            LambdaQuery<IvyConfig> configLambdaQuery = BeetlSqlUtil.NEW().defaultSQLManager().tableName(IvyConfig.class).lambdaQuery();
            IvyConfig ivyConfig = configLambdaQuery.andEq(IvyConfig::getId, ivyExecutor.getIvyConfigId()).single();

            FlowExecutor flowExecutor = FlowExecutorUtil.getFlowExecutor(ivyConfig);

            IvyContext ivyContext = new IvyContext();
            ivyContext.setIvyChain(ivyChain);
            ivyContext.setIvyEl(ivyEl);
            ivyContext.setIvyExecutor(ivyExecutor);
            ivyContext.setIvyConfig(ivyConfig);
            ivyContext.setFlowExecutor(flowExecutor);
            ivyContext.setXxlJobContext(XxlJobContext.getXxlJobContext());

            IvyLoadCmp.loadCmp(ivyEl);

            LiteFlowChainELBuilder.createChain().setChainId(ivyChain.getChainId()).setEL(ivyEl.getEl()).build();
            return execute2Resp(ivyChain.getChainId(),flowExecutor,ivyContext);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    private static LiteflowResponse execute2Resp(String id,FlowExecutor flowExecutor,IvyContext ivyContext){
        LiteflowResponse response = flowExecutor.execute2Resp(id,null,ivyContext);
        if(response.isSuccess()){
            XxlJobHelper.log(response.getExecuteStepStrWithTime());
            XxlJobHelper.handleSuccess(response.getExecuteStepStrWithTime());
        }else{
            Exception e = response.getCause();
            XxlJobHelper.log(e.getMessage());
            XxlJobHelper.handleFail(e.getMessage());
            e.printStackTrace();
        }
        return response;
    }

    private static LiteflowResponse execute2Future(String id,FlowExecutor flowExecutor,IvyContext ivyContext){
        Future<LiteflowResponse> future = flowExecutor.execute2Future(id, null,ivyContext);
        try {
            LiteflowResponse response = future.get();
            if(response.isSuccess()){
                XxlJobHelper.log(response.getExecuteStepStrWithTime());
                XxlJobHelper.handleSuccess(response.getExecuteStepStrWithTime());
            }else{
                Exception e = response.getCause();
                XxlJobHelper.log(e.getMessage());
                XxlJobHelper.handleFail(e.getMessage());
            }
            return response;
        } catch (InterruptedException e) {
            e.printStackTrace();
            XxlJobHelper.log(e.getMessage());
            XxlJobHelper.handleFail(e.getMessage());
        } catch (ExecutionException e) {
            XxlJobHelper.log(e.getMessage());
            XxlJobHelper.handleFail(e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

}
